onkeltortyfandomcom_de-20200213-history
C++/16 Bit-Variable in positive Binärzahl umwandeln
Ausgabe einer 16 Bit-Variable als Binärzahl In dieser Übung wollen wir uns eine Funktion schreiben, welche eine 16-Bit Variable und einen Zeiger auf ein char-Array übernimmt und darin die umgewandelte 16 Bit-Variable als eine Zeichenkette speichert, welche den Binärwert dieser Darstellen soll. In diesem Fall wollen wir den Modulo-Operator ("%") verwenden, um den Rest der Division durch 2 einer Zahl zu erhalten, um uns den Binärwert dadurch zu erstellen. Die Zahl muss nur nach jedem Durchlauf ebenfalls durch 2 geteilt werden, um im Raster des n²-Zahlensystems zu bleiben. Der Einfachkeit halber beschränken wir uns hier auf 16 Bit Datenbreite und auf positive Ganzzahlen als umzuwandelnde Werte. Es wird später noch sehr viel intensiver auf die Abarbeitung binärer Daten eingegangen. Hierzu zuerst der komplette Quellcode des Beispiels: #include //Headerdatei für den Befehl "cout" #include //Headerdatei für den Befehl "getch" #include //Headerdatei für den Befehl "strcat" #include //Headerdatei für den Befehl "itoa" /****** Funktion zur Übernahme einer 16 Bit Variable und zur *********/ /****** Speicherung einer Zeichenkette als dargestellten Binärwert ***/ void DezimalZuBinaer(unsigned short sDezimalwert, char* cBinArray, bool bAusgabe = true) { char cBin17 = {0}; //char-Array für 16 Bustaben + Nullterminierung char *pBin = cBin; //Zeiger auf das char-Array //Speicherung und Berechnung der Größe des Datentyps short sGroesse = sizeof(sDezimalwert) * 8; //Größe des Datentyps in Bit (2 Bytes * 8 = 16 Bits) //Ausgabe der Info, falls gewünscht if (bAusgabe) std::cout << "short sDezimalwert = " << sDezimalwert << ",Groesse: " << sGroesse << " Bit." << std::endl; //Durchlauf, gesteuert durch die Anzahl der Bits for (int i=0; i <= sGroesse-1; i++) { //Den Rest des Modulo speichern short sRest = sDezimalwert % 2; //Ausgabe von Infos pro Binärstelle, falls gewünscht if (bAusgabe) std::cout << "Stelle " << (i + 1) << ": " << sDezimalwert << " : 2 = " << sDezimalwert/2 << " Rest \t" << sRest << std::endl; //Halbierung des umzuwandelnden Dezimalwertes sDezimalwert = sDezimalwert / 2; //Zeiger auf char zum Speichern der Binärstelle von Funktion "itoa" char *cRest; //Umwandeln des Modulo-Rests mittels "itoa" und //Speicherung in cRest, Radix 10 (Dezimalsystem) itoa(sRest,cRest,10); //Kopieren des in char umgewandelten Rests in die entsprechende Binärstelle pBini = *cRest; } //Kopieren des fertigen Binärstrings in die in den //Argumenten übergebenen Arrays "cBinArray" strcpy(cBinArray, cBin); } int main(int argc, char *argv[]) { //Aufforderung ausgeben, eine positive Ganzzahl einzugeben std::cout << "Bitte geben Sie eine Ganzzahl im Bereich 0 bis 65535 ein:"; //Variable zum Speichern der Ganzzahl unsigned short sNummer = 0; //Abfrage des Werts in der Konsole und Speicherung in Variable sNummer std::cin >> sNummer; //Fehlerabfrage (Ungültige Eingabe?) if (std::cin.fail()) { //Fehlermeldung ausgeben std::cout << std::endl << "Fehler bei der Eingabe !" << std::endl; //Tastendruck abfragen getch(); //Programm beenden return 0; } else { //char-Array mit 17 Einträgen (16 Bits + Nullterminierung) char cArray17 = {0}; //Aufruf der Funktion zum Umwandeln des Werts in eine binäre Zeichenkette DezimalZuBinaer(sNummer, cArray, false); //Ausgabe des Binärwerts als Zeichenkette std::cout << "Ergebnis: " << cArray << std::endl; } //Tastendruck zum Beenden getch(); //Programmende return 0; } Es wird hier im folgenden die abschnittsweise Erklärung des Quellcodes aufgeführt: Konsolenausgabe und Abfrage des Wertes In Zeile 40 ist unser Programmeinsprungspunkt int main, ab welchen die Ausführung der Befehle beginnt. Zeile 43 erzeugt eine Aufforderung an den Benutzer in der Konsole, eine Ganzzahl im Wertbereich eines unsigned short einzugeben. Da wir eine Variable brauchen, in der wir diesen Wert speichern wollen, deklarieren wir diese in Zeile 45. In Zeile 47 weisen wir den Computer an, eine Eingabe des Benutzers in der Konsole abzuwarten und diese in der in Zeile 45 deklarierten Variable sNummer zu speichern. Sollte der Benutzer eine ungültige Eingabe machen (Zeichen statt Zahlen, zu großer Wert usw.), so vermerkt der Computer eine fehlerhafte Eingabe, wobei wir in Zeile 49 abfragen, ob dies der Fall ist. Falls ja, so werden die Zeilen 51 bis 56 abgearbeitet, wo zuerst in Zeile 52 eine Fehlermeldung an den Benutzer ausgegeben wird. Danach wartet der Computer in Zeile 54 durch den Befehl getch() einen Tastendruck des Benutzers ab und beendet in Zeile 56 mit return 0; das Programm. Deklaration des Zeichen-Arrays, Funktionsaufruf und Ergebnisausgabe Sollte die Eingabe gültig gewesen sein und in der Variabe sNummer ist ein gültiger Zahlenwert, so benötigen wir vor dem eigentlichen Funktionsaufruf ein Array, in dem wir genügend Platz haben, um den Binärwert als Zeichenkette zu speichern. Da wir wissen, dass der Zahlenwert nicht über 16 Bit Datenbreite hinaus geht und der Compiler an jedem Zeichen/jeder Zeichenkette eine Nullterminierung anhängt, so kommen wir auf eine Anzahl von 16 Zeichen + 1 Zeichen für die Nullterminierung = 17 Zeichen. Deshalb deklarieren wir in Zeile 60 mit char cArray17 = {0}; ein Array für 16 Zeichen und initialisieren jede Stelle mit einer Null, um Datenschrott durch nicht zugewiesenen Speicher zu vermeiden. Nun übergeben wir im Funktionsaufruf DezimalZuBinaer(sNummer, cArray, false); in Zeile 62 von links nach rechts gelesen folgende Argumente: * die Variable sNummer beeinhaltet den vom Benutzer eingegebenen Wert und soll ins binäre Format als Zeichenkette umgewandelt werden, * das Array cArray, welches 17 Zeichen breit ist, wird zur Speicherung des Ergebnisses übergeben. Aus ihm kann nach dem Funktionsaufruf der Wert aus sNummer als Binärzahl in Form einer Zeichenkette ausgelesen werden, * der boolsche Wert false, welcher die Ausgabe von Zusatzinformationen während des Funktionslaufs steuert. Wird false übergeben, so findet keine Ausgabe statt, andernfalls schon. Die Funktion "DezimalZuBinaer" Die Funktionsdeklaration Die Funktion DezimalZuBinaer wird in Zeile 8 mit void DezimalZuBinaer(unsigned short sDezimalwert, char* cBinArray, bool bAusgabe = true) deklariert. Hierbei * sagt der Rückgabetyp void aus, dass diese Funktion keinen Rückgabewert hat (engl. void = "nichts"), * ist das erste Argument unsigned short sDezimalwert die ins Binärsystem umzuwandelnde Dezimalzahl, * stellt das zweite Argument char* cBinArray einen Zeiger auf ein Array dar, in dem die ins Binärsystem umgewandelte Dezimalzahl als Zeichenkette gespeichert werden soll, * ist das dritte Argument bool bAusgabe = true ein mit dem Wert true initialisierter Wahrheitswert, welcher zur Steuerung einer erweiterten Ausgabe während der Funktionsabarbeitung dient. Dies kann man z. B. zum Debuggen von Funktionen verwenden. Vorbereitungen zur Umwandlung Zuerst wird das Array char cBin17 = {0}in Zeile 10 deklariert, welches in der for-Schleife zum Speichern der einzelnen Bitstellen verwendet wird. Dieses Array ist nur lokal gültig und wird nach der Abarbeitung der Funktion wieder freigegeben. Um Zugriff auf die einzelnen Stellen des Arrays zu haben, wird mit char *pBin = cBinin Zeile 11 ein Zeiger auf das Array deklariert. Die Größe des umzuwandelnden Datentyps lassen wir uns in Zeile 14 mit short sGroesse = sizeof(sDezimalwert) * 8 berechnen, wobei hierbei 2 Bytes * 8 Bits = 16 Bit Breite des Datentyps als Ergebnis berechnet werden. Sollte mit Variablen Datentypen gearbeitet werden, so kann diese Methode sehr praktisch sein. Falls das dritte Funktionsargument bool bAusgabe den Wert true beeinhaltet, so wird als nächstes in Zeile 16 eine kurze Info über den übergebenen Datentyp sowie seine Datenbreite ausgegeben. Die Schleife zur Umwandlung ins Binärformat Da der Computer die Stellen eines Array von 0 weg zählt, müssen wir die Schleife vom Wert 0 bis zum Größe des Datentyps in Bit -1 zählen lassen. Dies tun wir durch die Einleitung der Schleife in Zeile 18 vom ersten bis zum letzten Bit mit for (int i=0; i <= sGroesse-1; i++), wobei hier die Variable i durch i++ bei jedem Durchlauf jeweils um 1 erhöht wird. Um eine ganzzahlige Binärzahl zu errechnen, muss man diese durch 2 Teilen und den Rest (0 oder 1) als Binärstelle werten. Danach teilt man den Rest der Teilung wieder durch 2. Den Rest einer Teilung wird in C++ mit dem Modulo-Operator ("%") errechnet, weshalb wir in Zeile 21 mit short sRest = sDezimalwert % 2 den Rest der Teilung in der Variable sRest speichern. Ist nun die Option für die Ausgabe (bool bAusgabe = true) aktiviert, wird in Zeile 23 der Modulo-Rest und der Rest der Teilung ausgegeben. Da nun beim nächsten Durchlauf der Schleife der Rest des halben Dezimalwerts benötigt wird, wird dieser in Zeile 25 mit sDezimalwert = sDezimalwert / 2 halbiert. Nun wird in Zeile 28 ein Zeiger auf einen char erstellt, welcher in Zeile 31 mit itoa(sRest,cRest,10) als Wert den in ein Zeichen umgewandelten Rest aus der Variable sRest speichert. Die Funktion itoa ("Integer to ASCII") wandelt einen Dezimalwert (in unserem Fall den Rest in sRest) in ein ASCII-Zeichen um und speichert dieses nach einem bestimmten Zahlensystem (in unserem Fall 10 für Dezimal) ab. Somit erhalten wir in der Variable cRest den Binärwert der Stelle als Zeichen anstatt als Zahl. Nun wird in Zeile 33 dieses in cRest gespeicherte Zeichen in die entsprechende Stelle des Arrays char cBin17 gespeichert, indem man auf die entsprechende Stelle über den Zeiger auf das Array (pBin) zugreift: pBini = *cRest Kopieren des fertigen Arrays mit dem Binärwert Da nach dem Durchlauf der Schleife der Dezimalwert als eine in den Binärwert umgewandelte Zeichenkette im Array char cBin17 vorliegt, müssen wir diesen noch in das gewünschte Array kopieren, welches uns als Zeiger als zweites Argument der Funktion (char* cBinArray) übergeben wurde. Dazu bedienen wir uns der Funktion strcpy, welche uns mit strcpy(cBinArray, cBin) den Inhalt von cBin nach cBinArray kopiert, welches nach Beendigung der Funktion wieder im Quellcode der Hauptfunktion int main zur Verfügung steht. Dort wird der Inhalt des Arrays cBinArray, welches per Zeiger in cArray gespeichert wurde, in Zeile 64 ausgegeben. Ergebnis in der Konsole Hat man bool bAusgabe auf false gesetzt, so erhält man z. B. folgende Ausgabe in der Konsole: Bitte geben Sie eine Ganzzahl im Bereich 0 bis 65535 ein:65535 Ergebnis: 1111111111111111 Ist beim Funktionsaufruf DezimalZuBinaer(sNummer, cArray, true) der Parameter 3 auf true (oder ausgelassen, so ist er durch die Funktionsdeklaration auch auf true), so erhält man eine erweiterte Ausgabe: Bitte geben Sie eine Ganzzahl im Bereich 0 bis 65535 ein:65535 short sDezimalwert = 65535,Groesse: 16 Bit. Stelle 1: 65535 : 2 = 32767 Rest 1 Stelle 2: 32767 : 2 = 16383 Rest 1 Stelle 3: 16383 : 2 = 8191 Rest 1 Stelle 4: 8191 : 2 = 4095 Rest 1 Stelle 5: 4095 : 2 = 2047 Rest 1 Stelle 6: 2047 : 2 = 1023 Rest 1 Stelle 7: 1023 : 2 = 511 Rest 1 Stelle 8: 511 : 2 = 255 Rest 1 Stelle 9: 255 : 2 = 127 Rest 1 Stelle 10: 127 : 2 = 63 Rest 1 Stelle 11: 63 : 2 = 31 Rest 1 Stelle 12: 31 : 2 = 15 Rest 1 Stelle 13: 15 : 2 = 7 Rest 1 Stelle 14: 7 : 2 = 3 Rest 1 Stelle 15: 3 : 2 = 1 Rest 1 Stelle 16: 1 : 2 = 0 Rest 1 Ergebnis: 1111111111111111 Kategorie:C++